package MapperXmlUtils

import (
	"frame/utils/XmlUtils"
	"frame/utils/StringUtils"
	"strings"
	"regexp"
	"strconv"
)

func ParseMapper(filecontent string , method string, param map[string]interface{})(bool,error,string){
	var sqlcontent = "";
	var result = XmlUtils.Result{}
	if parseResult, err := XmlUtils.Parse(filecontent, &result); !parseResult {
		return false,err,""
	}
	var sqlstoken = result.Root.Tokens
GETEXCELCONTENTOUT_MAP:
	for _, v := range sqlstoken {
		var attrs = v.Attributes
		for _, attr := range attrs {
			if (attr.Name == "id") {
				//fmt.Println("attr.Name="+attr.Name)
				if (attr.Value == method) {
					sqlcontent = GetContentFromTokenAndExecProcess(&v,&param)
					break GETEXCELCONTENTOUT_MAP
				}
			}
		}
	}
	return true,nil,sqlcontent
}

func GetContentFromTokenAndExecProcess(token *XmlUtils.Token,param *map[string]interface{})(string){
	var result = "";
	if(token.Type=="DATA"){
		return token.Data
	}
	if(token.Type=="NODE"){
		//判断tokenName
		if(token.Name=="if"){
			var teststr string
			for _,t := range token.Attributes {
				//获取IF的配置
				if(t.Name=="test"){
					teststr = t.Value
				}
			}
			//执行IF判断
			//1.如果test为空，则报错
			if(StringUtils.IsEmpty(teststr)){
				panic("在加载Mapper文件时，发现IF测试的test条件为空")
			}

			//2、对表达式进行判断
			var testresult = processTestStr(teststr,param)

			//3、如果表达式为真，则返回IF中的内容
			if(testresult){
				for _,v := range token.Tokens {
					result +=GetContentFromTokenAndExecProcess(&v,param)
				}
			}
		}else if(token.Name=="trim"){
			//可扩展
			var trimstr = ""
			for _,v := range token.Tokens {
				trimstr +=GetContentFromTokenAndExecProcess(&v,param)
			}
			result += StringUtils.Trim(trimstr)
		}else{
			//其他类型节点
			for _,v := range token.Tokens {
				result +=GetContentFromTokenAndExecProcess(&v,param)
			}
		}

	}
	return result
}

func processTestStr(teststr string, param *map[string]interface{})(bool){
	//TODO 截至20180422212400，只支持单个表达式，将来待优化
	var getexprval = func(exp string,param *map[string]interface{})(interface{}){
		//4情况：
		//1、nil，转化为nil
		//2、字符串，则尝试从map中获取
		//3、数字，则无小数点转为int64，有小数点转化为float64
		//4、""或''包括的内容，转化为字符串
		exp = StringUtils.Trim(exp)
		var reg_isvar = regexp.MustCompile(`^[A-Za-z]+[0-9A-Za-z_]*$`)
		var reg_isint = regexp.MustCompile(`^[0-9]*$`)
		var reg_isfloat = regexp.MustCompile(`^[0-9\.]*$`)
		var reg_isstr = regexp.MustCompile(`^[\"\']+[^\"\']*[\"\']+$`)

		if(exp=="nil"){
			return nil
		}
		if(reg_isvar.MatchString(exp)){
			var mapval,found = (*param)[exp]
			if(found){
				return mapval
			}else{
				return nil
			}
			return nil
		}
		if(reg_isint.MatchString(exp)){
			val,err:=strconv.Atoi(exp)
			if err != nil {
				panic("在加载Mapper文件时，发现IF测试的test条件中有非法INT数字["+exp+"]")
			}
			return val
		}
		if(reg_isfloat.MatchString(exp)){
			val,err:=strconv.ParseFloat(exp,64)
			if err != nil {
				panic("在加载Mapper文件时，发现IF测试的test条件中有非法Float数字["+exp+"]")
			}
			return val
		}
		if(reg_isstr.MatchString(exp)){
			//去掉开始的引号和结束的引号，不区分双引号还是单引号
			return exp[1:len(exp)-1]
		}

		panic("在加载Mapper文件时，发现非法测试条件["+exp+"]")
	}
	if(strings.Index(teststr,"==")>0){
		var exp []string = strings.Split(teststr,"==")
		var exp1 = getexprval(exp[0],param)
		var exp2 = getexprval(exp[1],param)
		if(exp1 == exp2){
			return true
		}else{
			return false
		}
	}
	if(strings.Index(teststr,"!=")>0){
		var exp []string = strings.Split(teststr,"!=")
		var exp1 = getexprval(exp[0],param)
		var exp2 = getexprval(exp[1],param)
		if(exp1 != exp2){
			return true
		}else{
			return false
		}
	}
	panic("在加载Mapper文件时，发现非法测试条件["+teststr+"]")
	return false
}